/* ------------------------------------------------------------------------
 * Copyright (c) 2024-2025 [XD-AMCC TEAM]
 * [XD-AMCC] is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *        http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES
 * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 ----------------------------------------------------------------------- */


/* -----------------------------------------------------------------------

  LL(*) grammar of AMC in ANTLR's EBNF notation.

  *********** 本文件中的一些约定 ***********

  (1) 非终结符　　均以　小写字母打头，
  (2) 具名终结符　均以　大写字母打头 && 全部大写，
  (3) 匿名终结符　用一对单引号包围的字符串表示，如保留关键字、运算符、特殊符号等。
  (4) 因试图修改为 LL(1) 文法，所以尽力提取左因子、消除左递归。

  EBNF 形式产生式中的元符号说明：
  (1) 正闭包： s + 或 ( s ) + ， 输入中的 s 结构可以 连续 出现 `1..+∞` 次。
  (2) 星闭包： s * 或 ( s ) * ， 输入中的 s 结构可以 连续 出现 `0..+∞` 次。
  (3) 可缺省： s ? 或 ( s ) ? ， 输入中的 s 结构可以出现 `0..1` 次。
  (4) 多选一： ( ...|... )， 输入中可以出现括号中的、竖线分隔的任意一个结构。

*---------------------------------------------------------------------- */

grammar amc;


// -----------------------------------------------------------------------
// PART 1     Syntax    Rules
// -----------------------------------------------------------------------


// -----------------------------------------------------------------------
// PART 1.1  最顶层的两个结构
//

// 编译单元，文法的开始符号; 描述一个 AMC 源文件的语法结构。
// Tips: 源文件中的注释、起分隔作用的空白字符均被词法分析器丢弃了.
//
translationUnit             //------------------ LL(1) production 1
    :  ( declaration ) +    // 1..N 个声明形成的序列
    ;

declaration                 //------------------ LL(3) production 2,3
    : // LA1=typeName, LA2=ID, LA3=(, --> 函数定义
        funcDeclaration
    | // LA1=typeName, LA2=ID, LA3=others --> 变量定义
        varDeclaration
    ;


// -----------------------------------------------------------------------
// PART 1.2  变量声明。不支持非定义声明；初始式可选。
//

varDeclaration              //------------------ LL(1) production 4
    :  typeSpecifier           // 不能是 void
       initDeclarator                  //第 1 个变量定义
       ( ','   initDeclarator )*       //第 2..n 个变量定义
       ';'
    ;

// 单个变量的声明，初始式可省略
initDeclarator              //------------------ LL(1) production 5
    :  directDeclarator ( '=' initializer )?
    ;

directDeclarator            //------------------ LL(1) production 6
    : ID
      (
        ( '['  (INT_LITERAL)?  ']' )   // 数组, 第 1 维元素个数 可 省略
        ( '['   INT_LITERAL    ']' )*  // 第 2..n 维元素个数 不能 省略
      )?
    ;


initializer                 //------------------ LL(1) production 7..8
    :
        additiveExpression          // 标量初值, LA(1) 不是 '{'
    |
       '{'                          // 数组初值, LA(1)  是 '{'
           (
             initializer ( ','  initializer )*
           )?
       '}'
    ;


// -----------------------------------------------------------------------
// PART 1.3  函数声明
//

// AMCC 不支持函数的非定义声明。仅仅在语法上能识别它，
//      但语义分析时忽略该结构

funcDeclaration             //------------------ LL(1) production 11
    :  typeSpecifier  ID  '('  parameterList   ')'
       ( ';'                         // 函数的非定义声明,不被支持
       | compoundStatement           // 函数的定义--体
       )
    ;

parameterList               //------------------ LL(1) production 12, 13
    :
       parameter ( ',' parameter )*
    |
       /* ε */
    ;

parameter                   //------------------ LL(1) production 14
    :  typeSpecifier  directDeclarator
    ;


typeSpecifier               //------------------ LL(1) production 15~17
    :  INT | DOUBLE | VOID
    ;



// -----------------------------------------------------------------------
// PART 1.4  语句
//

statement                   //------------------ LL(2) production 31..36, reserve 37..40
    :  selectionStatement        // LA(1) 是 'if'
    |  iterationStatement        // LA(1) 是  'while'
    |  jumpStatement             // LA(1) 是 goto,break,continue,return
    |  compoundStatement         // LA(1) 是 '{'
    |  labeledStatement          // LA(1) 是 ID, LA(2) 是冒号
    |  expressionStatement       // LA(1)若是ID且 LA(2)不是冒号；或 LA(1) 是 其他
    ;

selectionStatement          //------------------ LL(1) production 41, reserve 42
    :  IF '(' expression ')' statement
       ( ELSE statement )?
    ;

// 设立该结构，以便于增设其他循环结构
iterationStatement          //------------------ LL(1) production 43, reserve 44..50
    :  WHILE '(' expression ')' statement
    ;

labeledStatement            //------------------ LL(1) production 51
    :  ID  ':'  statement
    ;

jumpStatement               //------------------ LL(1) production 52..55
    :  (  BREAK
       |  CONTINUE
       |  GOTO ID     // label ID is defined in labeledStatement
       |  RETURN ( expression )?
       )
       ';'
    ;

expressionStatement         //------------------ LL(1) production 56
    :  ( expression )?   ';'
    ;

compoundStatement           //------------------ LL(1) production 57
    :  '{'
           ( blockItem )*
       '}'
    ;

blockItem                   //------------------ LL(1) production 58..59
    :  declaration          // LA(1) 是 类型名
    |  statement            // LA(1) 不是类型名
    ;



// -----------------------------------------------------------------------
//
// PART 1.5  表达式
//
// 【提示】
// 当前文法描述的表达式结构 蕴含了 相关优先级和结合性：
//   1. 结合性（遵守 C 语言约定）
//      :-) 一元前缀运算、赋值 为 右结合，其他均为左结合。
//   2. 优先级：遵守 C 语言约定
//


expression                  //------------------ LL(1) production 71
    :  assignmentExpression
    ;

// 有左值的表达式: 变量或数组引用
leftValue                   //------------------ LL(1) production 72
    :  ID  ( '['  expression    ']' )*
    ;


// 这里 需要 LL(*):
// LL(2) 的两种情况： ID = ,  ID (
// LL(*) 的情况： 对于数组元素可能有  ID[expr][expr]... =
assignmentExpression        //------------------ LL(*) production 73..74
    :  leftValue
       ('='  | '+=' | '-=' | '*=' | '/=' | '%=')
       assignmentExpression
    |
       // if LA(1..K) is left-Value,  LA(K+1) is not assignOptr;
       // if LA(1) is ID and LA(2) is '(',  this is a func-call.
//       conditionalExpression
       logicalOrExpression
    ;

/* obsolete, NO support
conditionalExpression       //------------------ LL(1) production 75
    :  logicalOrExpression
    ;
*/

logicalOrExpression         //------------------ LL(1) production 76
    :  logicalAndExpression
       (
          '||' logicalAndExpression
       )*
    ;

logicalAndExpression        //------------------ LL(1) production 77
    :  equalityExpression
       (
          '&&'  equalityExpression
       )*
    ;

equalityExpression          //------------------ LL(1) production 78
    :  relationalExpression
       (
          ('=='|'!=')  relationalExpression
       )*
    ;

relationalExpression        //------------------ LL(1) production 79
    :  additiveExpression
       (
          ('<' | '<=' | '>' | '>=')  additiveExpression
       )*
    ;

additiveExpression          //------------------ LL(1) production 80
    :  multiplicativeExpression
       (
          ('+'|'-')   multiplicativeExpression
       )*
    ;

multiplicativeExpression    //------------------ LL(1) production 81
    :  unaryExpression
       (
          ('*'|'/'|'%')   unaryExpression
       )*
    ;

unaryExpression             //------------------ LL(1) production 82..83, reserve 84..86
    :
       // 保留 右递归 形式，分析树规整，但 树较高。
       // 右递归形式 方便 语义分析 的处理。
       ('+' | '-' | '!') unaryExpression
    |
       primaryExpression
    ;


primaryExpression           //------------------ LL(2) production 87..91, reserve 92..95
    :  INT_LITERAL
    |  REAL_LITERAL
    |  '(' expression ')'
    |  functionCall   // LA(1) is ID, and LA(2) is '('
    |  leftValue      // LA(1) is ID, and LA(2) is not '('
    ;

functionCall                //--------------- production 96
    : ID  '('  argumentList  ')'
    ;

argumentList                //--------------- production 97, 98
    :  assignmentExpression
       (
          ',' assignmentExpression
       )*
    |
       /* ε */
    ;


//
//  END  OF  GRAMMAR
//


// -----------------------------------------------------------------------
// PART 2     Lexical    Rules (partial)
// -----------------------------------------------------------------------


DOUBLE  : 'double'      ;
INT     : 'int'         ;
VOID    : 'void'        ;

IF      : 'if'          ;
ELSE    : 'else'        ;
GOTO    : 'goto'        ;
WHILE   : 'while'       ;
BREAK   : 'break'       ;
CONTINUE: 'continue'    ;
RETURN  : 'return'      ;


ID  : [a-zA-Z_][a-zA-Z_0-9]*
    ;

// 实数字面量，不支持C语言的类型后缀字符
REAL_LITERAL
    :   [0-9]+
        (  '.'        [0-9]+  )?
        (  [eE] [-+]? [0-9]+  )?
    ;

// 整型字面量，不支持C语言的类型后缀字符
INT_LITERAL
    : INT_LITERAL_DEC
    | INT_LITERAL_OCT
    | INT_LITERAL_HEX
    | INT_LITERAL_BIN
    ;

//关于 4 种进制 整数字面量的 辅助定义
fragment INT_LITERAL_DEC : [1-9] [0-9]*          ;
fragment INT_LITERAL_OCT : '0' [0-7]*            ;
fragment INT_LITERAL_HEX : '0' [xX] [0-9a-fA-F]+ ;
fragment INT_LITERAL_BIN : '0' [bB] [01]+        ;



// Separators

LPAREN   : '('  ;
RPAREN   : ')'  ;
LBRACE   : '{'  ;
RBRACE   : '}'  ;
LBRACKET : '['  ;
RBRACKET : ']'  ;
SEMI     : ';'  ;
COMMA    : ','  ;
COLON    : ':'  ;

// Operators

OP_ASSIGN: '='  ;
OP_LT    : '<'  ;
OP_LE    : '<=' ;
OP_GT    : '>'  ;
OP_GE    : '>=' ;
OP_EQ    : '==' ;
OP_NE    : '!=' ;

// operators on integer / real number
OP_PLUS  : '+'  ;
OP_MINUS : '-'  ;
OP_MUL   : '*'  ;
OP_DIV   : '/'  ;
OP_MOD   : '%'  ;

OP_NOT   : '!'  ;
OP_AND   : '&&' ;
OP_OR    : '||' ;

// discard comments in lexer

COMMENT_LINE  :  '//' ~[\r\n]*   -> skip
    ;

COMMENT_BLOCK :  '/*' .*? '*/'   -> skip
    ;

// discard white spaces in lexer
WS  : [ \r\n\t\f]+ -> skip
    ;

// AMCC 可识别，但不支持（报错）
CHAR_LITERAL : '\'' CCharSequence '\''
    ;

// AMCC 可识别，但不支持（报错）
StringLiteral :  '"' SCharSequence? '"'
    ;


// 下面是用于描述 字符字面量、字符串字面量的 辅助定义

fragment CCharSequence : CChar+
    ;

fragment CChar : ~['\\\r\n] | EscapeSequence
    ;

fragment EscapeSequence
    : SimpleEscapeSequence
    | OctalEscapeSequence
    | HexadecimalEscapeSequence
    ;

fragment SimpleEscapeSequence
    : '\\' ['"?abfnrtv\\]
    ;

fragment OctalEscapeSequence
    : '\\' OctalDigit ( OctalDigit )?  ( OctalDigit )?
    ;

fragment HexadecimalEscapeSequence
    : '\\x' HexadecimalDigit ( HexadecimalDigit )?
    ;

fragment OctalDigit  : [0-7]
    ;

fragment HexadecimalDigit : [0-9a-fA-F]
    ;

fragment SCharSequence : SChar+
    ;

fragment SChar
    : ~["\\\r\n]
    | EscapeSequence
    ;

//
//  END  OF  Lexical   Rules
//

// End-Of-File
